#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define ARRAY_NUM(arr) (sizeof(arr)/sizeof(arr[0]))
struct file_head
{
    int filesize;
    char fileName[255];
};

struct file_head fhd = {0};

int fileZIP(const char *fName, FILE *fp)
{
    FILE *Tfp = fopen(fName, "rb"); // 打开文件
    if (NULL == Tfp)
    {
        printf("文件:%s 打开失败！\n", fName);
        return -1;
    }

    // 计算文件大小
    fseek(Tfp, 0, SEEK_END);
    int FileSize = ftell(Tfp);
    fseek(Tfp, 0, SEEK_SET);

    // 写入文件头
    fhd.filesize = FileSize;
    strcpy(fhd.fileName, fName);
    fwrite(&fhd, 1, sizeof(fhd), fp); // 文件头写入pack文件

    char *buffer = (char *)malloc(FileSize);
    if (buffer == NULL)
    {
        printf("内存分配失败！\n");
        fclose(Tfp);
        return -1;
    }
   // 全部读出写入buff
    fread(buffer, 1, FileSize, Tfp); 
    fwrite(buffer, 1, FileSize, fp); // 写入pack
    fclose(Tfp);
    free(buffer); // 释放动态内存
    buffer = NULL;
    printf("文件:%s 写入成功! 文件大小:%d\n", fName, FileSize);
    return 0;
}

// ----------------------
int fileEXT(const char *fname)
{ // 执行文件释放
    // 打开pack文件
    FILE *fp = fopen(fname, "rb");
    if (NULL == fp)
    {
        printf("pack文件打开失败!\n");
        return -1;
    }

    // 循环读取文件
    while (1)
    {
        // 获取文件头
        size_t ret = fread(&fhd, 1, sizeof(fhd), fp);
        if (ret < sizeof(fhd))
        {
            break;
        }

        const char *fileName = fhd.fileName;
        int FileSize = fhd.filesize;

        // 建立释放文件 - 准备写入
        FILE *Tfp = fopen(fileName, "wb");
        if (NULL == Tfp)
        {
            // 出现错误 - 跳出本循环 -
            printf("文件 %s 打开失败，跳过该文件！\n", fileName);
            fseek(fp, FileSize, SEEK_CUR);
            continue;
        }

        // 写入文件 - 建立动态空间 -
        char *buffer = (char *)malloc(FileSize);
        if (buffer == NULL)
        {
            printf("内存分配失败！\n");
            fclose(Tfp);
            fseek(fp, FileSize, SEEK_CUR);
            continue;
        }

        // 读取文件内容写入buffer
        fread(buffer, 1, FileSize, fp);
        // 将buffer 写入释放文件
        fwrite(buffer, 1, FileSize, Tfp);
        fclose(Tfp);
        free(buffer);
        printf("文件: %s 释放完成！文件大小 %d;\n", fileName, FileSize);
    }

    fclose(fp);
    return 0;
}

// ----
int main(int argc, char *argv[])
{
    SetConsoleOutputCP(CP_UTF8);
    // "-zip" 合并文件 "-ext" 释放文件
    if (argc < 3)
    {
        printf("输入格式错误：帮助: filezip.exe -zip 1.file 2.file ....\n");
        printf("输入格式错误：帮助: filezip.exe -ext filename.pack\n");
        return -1;
    }

    const char *flg = argv[1];
    if (strcmp(flg, "-zip") == 0)
    { // ---执行合并任务--
        // --创建pack文件
        FILE *fp = fopen("ZipFile.pack", "wb");
        if (NULL == fp)
        {
            printf("新建Pack文件失败!");
            return -1;
        }

        for (int i = 2; i < argc; i++)
        {
            const char *fName = argv[i]; // 获取文件名称；
            fileZIP(fName, fp);
        }

        fclose(fp);
        return 0;
    }
    else if (strcmp(flg, "-ext") == 0)
    {
        // ---执行释放任务
        fileEXT(argv[2]);
        return 0;
    }
    else
    {
        printf("输入格式错误：帮助: filezip.exe -zip 1.file 2.file ....\n");
        printf("输入格式错误：帮助: filezip.exe -ext filename.pack\n");
        return -1;
    }
}
    